/**
 * Copyright [2020] [LiBo/Alex of copyright liboware@gmail.com ]
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package report.tools;

import org.apache.commons.collections4.CollectionUtils;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @project-name:lhy-report
 * @package-name:com.lhy.lhy.report.tools
 * @author:LiBo/Alex
 * @create-date:2021-09-16 22:53
 * @copyright:libo-alex4java
 * @email:liboware@gmail.com
 * @description:
 */
public class AbsolutelyAverageDateRangeSplitter extends AbstractDateRangeSplitter {


    /**
     * 数量分片
     * @param splitNum
     */
    public AbsolutelyAverageDateRangeSplitter(int splitNum) {
        super(splitNum);
    }


    /**
     * 单元分片
     * @param dateSplitValue
     * @param dateSplitUnit
     */
    public AbsolutelyAverageDateRangeSplitter(long dateSplitValue, ChronoUnit dateSplitUnit) {
        super(dateSplitValue, dateSplitUnit);
    }

    /**
     * 分片时间操作
     * @param startDate
     * @param endDate
     * @return
     */
    @Override
    public List<DateRangeSplit> splitDateByUnit(LocalDateTime startDate, LocalDateTime endDate) {
        Objects.requireNonNull(this.getDateSplitUnit(),"no support the unit range process!");
        Objects.requireNonNull(this.getDateSplitValue(),"no support the unit range process!");
        long durationRange = computeTheDateDuration(startDate,endDate);
        if(durationRange <= 0 || getDateSplitValue() <=0 ){
            return new ArrayList<>(0);
        }
        long extCount = durationRange % getDateSplitValue();
        long cycleSize = durationRange / getDateSplitValue()+((extCount!=0)?1:0);
        setSplitNum((int) cycleSize);
        List<DateRangeSplit> dateRangeSplits = new ArrayList<>((int) cycleSize);
        // 进行初始化整体分片数据集合
        LocalDateTime subStartDate = startDate;
        LocalDateTime subEndDate = null;
        for(int start = 0 ; start < cycleSize ; start++){
            // 初次执行，只需要计算结束时间
            if(start == 0) {
                subEndDate = subStartDate.plus(this.getDateSplitValue(), getDateSplitUnit());
                subEndDate = subEndDate.isAfter(endDate) ? endDate : subEndDate;
            }
            // 非初次执行，需要计算下一轮的开始时间和结束时间！
            else {
                // 计算下一阶段的开始时间
                subStartDate = subEndDate.plus(1, ChronoUnit.SECONDS);
                boolean overout = subStartDate.isAfter(endDate);
                // 计算下一阶段的结束时间
                if(overout){
                    break;
                }else{
                    subEndDate = subStartDate.plus(this.getDateSplitValue(), getDateSplitUnit());
                    subEndDate = subEndDate.isAfter(endDate)?endDate:subEndDate;
                }
            }
            dateRangeSplits.add(new DateRangeSplit(start, Date.from(subStartDate.atZone(ZoneId.systemDefault()).toInstant()),
                    Date.from(subEndDate.atZone(ZoneId.systemDefault()).toInstant())));
        }
        if(CollectionUtils.isNotEmpty(dateRangeSplits)){
            DateRangeSplit dataRangeSplitter = dateRangeSplits.get(dateRangeSplits.size()-1);
            // 添加补偿机制控制
            if(!dataRangeSplitter.getSplitEndDate().equals(endDate)){
                dataRangeSplitter.setSplitEndDate(Date.from(endDate.atZone( ZoneId.systemDefault()).toInstant()));
            }
        }
        return dateRangeSplits;
    }

    /**
     * 分片时间操作(会存在误差值)
     * @param startDate
     * @param endDate
     * @return
     */
    @Override
    public List<DateRangeSplit> splitDateByNum(LocalDateTime startDate, LocalDateTime endDate) {
        Objects.requireNonNull(this.getSplitNum(),"no support the num range process!");
        long durationRange = computeTheDateDuration(startDate,endDate);
        if(getSplitNum() <= 0){
            return new ArrayList<>(0);
        }
        long rangeDate = durationRange / getSplitNum();
        setDateSplitValue(rangeDate);
        //默认以天为间隔单位
        setDateSplitUnit(ChronoUnit.DAYS);
        return splitDateByUnit(startDate,endDate);
    }



    public static void main(String[] args){
        System.out.println(new AbsolutelyAverageDateRangeSplitter(10,ChronoUnit.DAYS).
                splitDateByUnit(LocalDateTime.of(2021,9,7,0,0)
                ,LocalDateTime.of(2021,9,10,23,59,59)));;
    }


}
